package com.huatai.common.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import lombok.SneakyThrows;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @program: ht-system
 * @description: 转换工具
 * @author: songxiude
 * @create: 2023-03-01 13:37
 **/
public class BeanMapUtils {

	/**
	 * 将实体类对象属性转化为map对象
	 * @param t
	 * @param <T>
	 * @return
	 */
	public static <T> Map<String, Object> beanToMap(T t) {
		Map<String, Object> map = new HashMap<>();
		if (t != null) {
			if (t instanceof JSONObject){
				return (JSONObject)t;
			}
			BeanMap beanMap = BeanMap.create(t);
			for (Object key : beanMap.keySet()) {
				map.put(key.toString(), beanMap.get(key));
			}
		}
		return map;
	}


	/**
	 * 将map对象中转化为实体类对象
	 * @param map
	 * @param clazz
	 * @param <T>
	 * @return
	 * @throws Exception
	 */
	public static <T> T mapToBean(Map<String, Object> map,Class<T> clazz) throws Exception {
		T bean = clazz.newInstance();
		if (bean instanceof JSONObject){
			JSONObject jsonObject = (JSONObject)bean;
			Set<Map.Entry<String, Object>> entries = map.entrySet();
			for (Map.Entry<String, Object> entry : entries) {
				jsonObject.put(entry.getKey(),entry.getValue());
			}
			return (T)jsonObject;
		}
		BeanMap beanMap = BeanMap.create(bean);
		beanMap.putAll(map);
		return bean;
	}

	/**
	 * 通过lambda表达式将List<JavaBean>转化为List<Map<String, Object>>
	 * @param objList
	 * @param <T>
	 * @return
	 */
	public static <T> List<Map<String, Object>> listBeanToListMap(List<T> objList) {
		return objList.stream().map(new Function<T, Map<String, Object>>() {
			@Override
			public Map<String, Object> apply(T t) {
				Map<String,Object> map = Maps.newHashMap();
				if (t instanceof JSONObject){
					return (JSONObject)t;
				}
				BeanMap beanMap = BeanMap.create(t);
				for (Object key : beanMap.keySet()) {
					map.put(key.toString(), beanMap.get(key));
				}
				return map;
			}
		}).collect(Collectors.toList());
	}

	/**
	 * 通过lambda表达式将List<Map<String, Object>>转化为List<JavaBean>
	 * @param mapList
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> listMapToListBean(List<Map<String,Object>> mapList,Class<T> clazz) {
		return mapList.stream().map(new Function<Map<String, Object>,T>() {
			@SneakyThrows
			@Override
			public T apply(Map<String, Object> map) {
				T t = clazz.newInstance();
				if (t instanceof JSONObject){
					return (T)map;
				}
				BeanMap beanMap = BeanMap.create(t);
				beanMap.putAll(map);
				return t;
			}
		}).collect(Collectors.toList());
	}


	/**
	 * 根据orderNo排序树形结构的每一个层级
	 * @param list
	 * @return
	 */
	public static List<Map<String, Object>> sortJava8Map(List<Map<String, Object>> list){
		if(CollectionUtils.isEmpty(list)){
			return Lists.newArrayList();
		}
		//关键之处，一行代码搞定
		list.sort(Comparator.comparing(m -> String.valueOf(m.get("sort"))));
		return list;
	}
	/**
	 * 根据父级节点获取所有的子集节点
	 * @param parentNode
	 * @param allList
	 * @return
	 */
	public static List<Map<String, Object>> getJava8Children(Map<String,Object> parentNode, List<Map<String, Object>> allList){
		return allList.stream()
			.filter(curNode -> ObjectUtil.isNotEmpty(curNode.get("parentId")) && Objects.equals(curNode.get("parentId"),parentNode.get("id")))
			.peek(m -> m.put("children", getJava8Children(m,allList))).collect(Collectors.toList());
	}
	/**
	 * 获取树形结构
	 * @param mapList
	 * @return treeList 树形结果集
	 */
	public static List<Map<String, Object>> getJava8ResultTree(List<Map<String, Object>> mapList){
		if (CollectionUtils.isEmpty(mapList)){
			return Lists.newArrayList();
		}
		//filter过滤出所有的一级节点
		return mapList.stream()
			.peek(m -> m.put("children", getJava8Children(m, mapList))).collect(Collectors.toList());
	}


	//新的方式获取递归
	public static List<Map<String, Object>> getChildrens(Map<String, Object> root, List<Map<String, Object>> list){
		return list.stream().filter(m-> Objects.equals(m.get("parentId"),root.get("id")))
			.peek((m)->m.put("children",getChildrens(m,list))).collect(Collectors.toList());
	}
}
